package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.constants.WemediaConstants;
import com.heima.model.wemedia.constants.WmNewsMessageConstants;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsContent;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmNewsTaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.heima.model.wemedia.constants.WemediaConstants.WM_NEWS_TYPE_AUTO;

/**
 * @program: heima-leadnews
 * @description: 自媒体文章业务实现
 * @author: ryp
 * @create: 2023-04-27 11:25
 **/
@Slf4j
@Service
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Autowired
    private WmNewsAutoScanService wmNewsAutoScanService;

    @Autowired
    private WmNewsTaskService wmNewsTaskService;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * 功能描述: 查询自媒体文章
     *
     * @param dto
     * @return : com.heima.model.common.dtos.PageResponseResult
     */
    @Override
    public ResponseResult findAll(WmNewsPageReqDto dto) {
        //0.校验参数-分页条件
        dto.checkParam();
        //1.构建查询条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();
        //状态条件
        Short status = dto.getStatus();
        if (status != null) {
            queryWrapper.eq(WmNews::getStatus, status);
        }
        //频道条件
        Integer channelId = dto.getChannelId();
        if (channelId != null) {
            queryWrapper.eq(WmNews::getChannelId, channelId);
        }
        //时间条件
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();
        SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
        if (beginPubDate != null) {
            String beginStr = format.format(beginPubDate);
            LocalDate begin = LocalDate.parse(beginStr, DateTimeFormatter.ISO_LOCAL_DATE);
            queryWrapper.ge(WmNews::getPublishTime, begin);
        }
        if (endPubDate != null) {
            String endStr = format.format(endPubDate);
            LocalDate end = LocalDate.parse(endStr, DateTimeFormatter.ISO_LOCAL_DATE);
            queryWrapper.lt(WmNews::getPublishTime, end);
        }
        //关键字条件
        String keyword = dto.getKeyword();
        if (StringUtils.isNotEmpty(keyword)) {
            queryWrapper.like(WmNews::getTitle, keyword);
        }
        //构建分页条件
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());
        //排序条件
        queryWrapper.orderByDesc(WmNews::getPublishTime);
        //用户条件
        Integer id = WmThreadLocalUtil.getUser().getId();
        if (id == null) {
            return PageResponseResult.okResult(null);
        }
        queryWrapper.eq(WmNews::getUserId, id);
        //解析结果
        Page<WmNews> pageResult = wmNewsMapper.selectPage(page, queryWrapper);
        long total = pageResult.getTotal();
        List<WmNews> records = pageResult.getRecords();

        PageResponseResult pr = new PageResponseResult();
        pr.setCurrentPage(dto.getPage());
        pr.setSize(dto.getSize());
        pr.setTotal(Integer.valueOf(total + ""));
        pr.setData(records);
        pr.setCode(200);
        pr.setErrorMessage(AppHttpCodeEnum.SUCCESS.getErrorMessage());
        return pr;
    }

    /**
     * 功能描述: 文章发布-保存草稿或提交审核
     *
     * @param dto
     * @param draft
     * @return : com.heima.model.common.dtos.ResponseResult
     */
    @Override
    public ResponseResult submitNews(WmNewsDto dto, Boolean draft) throws Exception {
        Integer id = dto.getId();
        WmNews wmNews = new WmNews();
        //1.判断是否为草稿
        if (draft) {
            if (id == null) {
                //新增草稿
                //文章内容的封装
                wmNews = completion(dto, wmNews);
                wmNewsMapper.insert(wmNews);
                return ResponseResult.okResult(200, "保存草稿成功！");
            }
            removeRelationship(id);
            wmNewsMapper.updateById(wmNews);

            return ResponseResult.okResult(200, "修改草稿成功！");
        }
        //2.提交审核，判断是新增还是修改
        List<Integer> metarialIds = null;
        if (id == null) {
            //新增文章提交审核
            //1）补全数据
            wmNews = completion(dto, wmNews);
            wmNewsMapper.insert(wmNews);
            //批量添加文章和素材关联关系---wmNews.getId()、素材列表中素材的Id
            metarialIds = getMetarialIds(dto);
            wmNewsMaterialMapper.saveRelations(metarialIds, wmNews.getId(), (short) 0);
            //wmNewsAutoScanService.autoScanWmNews(id);
            wmNewsTaskService.addNewsToTask(wmNews.getId(), wmNews.getPublishTime());
            return ResponseResult.okResult(200, "新增文章提交审核成功！");
        }
        removeRelationship(id);
        wmNews = completion(dto, wmNews);
        wmNewsMapper.updateById(wmNews);
        metarialIds = getMetarialIds(dto);
        wmNewsMaterialMapper.saveRelations(metarialIds, wmNews.getId(), (short) 0);
        //wmNewsAutoScanService.autoScanWmNews(id);
        wmNewsTaskService.addNewsToTask(wmNews.getId(), wmNews.getPublishTime());
        return ResponseResult.okResult(200, "修改文章提交审核成功！");
    }

    /**
     * 功能描述: 自媒体文章上下架
     *
     * @param dto
     * @return : com.heima.model.common.dtos.ResponseResult
     */
    @Override
    public ResponseResult downOrUp(WmNewsDto dto) {
        //0.校验参数
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "无效参数");
        }
        //1.判断文章是否存在
        Integer id = dto.getId();
        WmNews wmNews = getById(id);
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST, "数据不存在");
        }
        //2.判断文章是否发布
        Short status = wmNews.getStatus();
        if (!status.equals(WmNews.Status.PUBLISHED.getCode())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前文章未发布,不可执行上下架操作");
        }
        //3.修改文章上下架状态
        Short enable = dto.getEnable();
        if (enable != null && enable > -1 && enable < 2) {
            update(Wrappers.<WmNews>lambdaUpdate().set(WmNews::getEnable, enable).eq(WmNews::getId, id));
        }
        //4.通过kafka通知article端文章上下架
        Long articleId = wmNews.getArticleId();
        if (articleId != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("articleId", articleId);
            map.put("enable", enable);
            kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 功能描述: 封装WmNews对象
     *
     * @param dto
     * @param wmNews
     * @return : com.heima.model.wemedia.pojos.WmNews
     */
    public WmNews completion(WmNewsDto dto, WmNews wmNews) {
        BeanUtils.copyProperties(dto, wmNews);
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        wmNews.setCreatedTime(new Date());
        wmNews.setStatus((short) 0);
        wmNews.setEnable((short) 1);
        List<String> imageList = dto.getImages();
        if (dto.getType() == -1) {//类型为自动
            short type = 0;
            //从内容中提取图片信息
            Set<String> imgs = new HashSet<>();
            String content = dto.getContent();
            if (StringUtils.isNotBlank(content)) {
                List<WmNewsContent> contentList = JSONObject.parseArray(content, WmNewsContent.class);
                for (WmNewsContent wmNewsContent : contentList) {
                    if ("image".equals(wmNewsContent.getType())) {
                        imgs.add(wmNewsContent.getValue());
                        continue;
                    }
                }
            }
            int size = imgs.size();
            if (size < 1) {
                type = 0;
            } else if (size >= 3) {
                type = 3;
                imageList = imgs.stream().limit(3).collect(Collectors.toList());
            } else {
                type = 1;
                imageList = imgs.stream().limit(1).collect(Collectors.toList());
            }
            wmNews.setType(type);
        }
        wmNews.setImages(StringUtils.join(imageList, ","));//现成方法
        return wmNews;
    }

    /**
     * 功能描述: 删除文章和素材关联关系
     *
     * @param id 自媒体文章ID
     * @return : void
     */
    public void removeRelationship(Integer id) {
        LambdaQueryWrapper<WmNewsMaterial> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WmNewsMaterial::getNewsId, id);
        wmNewsMaterialMapper.delete(queryWrapper);
    }

    /**
     * 功能描述: 获取封面图片列表
     *
     * @param dto 前端传递的请求参数
     * @return : java.util.List<java.lang.String>
     */
    public List<String> coverImages(WmNewsDto dto) {
        List<String> imageList = dto.getImages();
        if (dto.getType() == -1) {//类型为自动
            short type = 0;
            //从内容中提取图片信息
            Set<String> imgs = new HashSet<>();
            String content = dto.getContent();
            if (StringUtils.isNotBlank(content)) {
                List<WmNewsContent> contentList = JSONObject.parseArray(content, WmNewsContent.class);
                for (WmNewsContent wmNewsContent : contentList) {
                    if ("image".equals(wmNewsContent.getType())) {
                        imgs.add(wmNewsContent.getValue());
                        continue;
                    }
                }
            }
            int size = imgs.size();
            if (size < 1) {
                type = 0;
            } else if (size >= 3) {
                type = 3;
                imageList = imgs.stream().limit(3).collect(Collectors.toList());
            } else {
                type = 1;
                imageList = imgs.stream().limit(1).collect(Collectors.toList());
            }
        }
        return imageList;
    }

    /**
     * 功能描述: 根据素材的url地址列表，获取素材的id列表
     *
     * @param dto
     * @return : java.util.List<java.lang.Integer>
     */
    public List<Integer> getMetarialIds(WmNewsDto dto) {
        List<String> coverImages = coverImages(dto);
        LambdaQueryWrapper<WmMaterial> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(WmMaterial::getUrl, coverImages);
        queryWrapper.select(WmMaterial::getId);
        List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(queryWrapper);
        List<Integer> wmMaterialIds = wmMaterials.stream().map(wmMaterial -> wmMaterial.getId()).collect(Collectors.toList());
        return wmMaterialIds;
    }
}

